#ifndef _ELF_H
#define _ELF_H

/* values for elf_phdr.p_type */
#define PT_NULL    0
#define PT_LOAD    1
#define PT_DYNAMIC 2
#define PT_INTERP  3
#define PT_NOTE    4
#define PT_SHLIB   5
#define PT_PHDR    6
#define PT_LOPROC  0x70000000
#define PT_HIPROC  0x7fffffff

/* values for elf_phdr.p_flags */
#define PF_R	0x4
#define PF_W	0x2
#define PF_X	0x1

/* values for elfhdr.e_type */
#define ET_NONE   0
#define ET_REL    1
#define ET_EXEC   2
#define ET_DYN    3
#define ET_CORE   4
#define ET_LOPROC 5
#define ET_HIPROC 6

/* values for elfhdr.e_machine */
#define EM_386   3

struct elfhdr{
	unsigned char e_ident[16];
	unsigned short  e_type;
	unsigned short e_machine;
	unsigned long   e_version;
	unsigned long e_entry; 
	unsigned long e_phoff;
	unsigned long e_shoff;
	unsigned long e_flags;
	unsigned short e_ehsize;
	unsigned short e_phentsize;
	unsigned short e_phnum;
	unsigned short e_shentsize;
	unsigned short e_shnum;
	unsigned short e_shstrndx;
};

struct elf_phdr{
	unsigned long p_type;
	unsigned long p_offset;
	unsigned long p_vaddr;
	unsigned long p_paddr;
	unsigned long p_filesz;
	unsigned long p_memsz;
	unsigned long p_flags;
	unsigned long p_align;
};


#define str_eq(s1, s2)	(strcmp(s1, s2) == 0)
#define strn_eq(s1, s2, n) (strncmp(s1, s2, n) == 0)

/*
	Elf32_Addr      4       4       Unsigned program address
	Elf32_Half      2       2       Unsigned medium integer
	Elf32_Off       4       4       Unsigned file offset
	Elf32_Sword     4       4       Signed large integer
	Elf32_Word      4       4       Unsigned large integer
	unsigned char   1       1       Unsigned small integer
*/

typedef unsigned long Elf32_Addr;
typedef unsigned short Elf32_Half;
typedef unsigned long Elf32_Off;
typedef signed long Elf32_Sword;
typedef unsigned long Elf32_Word;

#define EI_NIDENT 16

typedef struct
{
      unsigned char       e_ident[EI_NIDENT];
      Elf32_Half          e_type;
      Elf32_Half          e_machine;
      Elf32_Word          e_version;
      Elf32_Addr          e_entry;
      Elf32_Off           e_phoff;
      Elf32_Off           e_shoff;
      Elf32_Word          e_flags;
      Elf32_Half          e_ehsize;
      Elf32_Half          e_phentsize;
      Elf32_Half          e_phnum;
      Elf32_Half          e_shentsize;
      Elf32_Half          e_shnum;
      Elf32_Half          e_shstrndx;
  } Elf32_Ehdr;


/* e_type */
#define ET_NONE         0		// No file type
#define ET_REL          1		// Relocatable file
#define ET_EXEC         2		// Executable file
#define ET_DYN          3		// Shared object file
#define ET_CORE         4		// Core file

/* e_machine */
#define EM_NONE       0			// No machine
#define EM_M32        1			// AT&T WE 32100
#define EM_SPARC      2			// SPARC
#define EM_386        3			// Intel 80386
#define EM_68K        4			// Motorola 68000
#define EM_88K        5			// Motorola 88000
#define EM_860        7			// Intel 80860
#define EM_MIPS       8			// MIPS RS3000

/* e_version */
#define EV_NONE        0		// Invalid version
#define EV_CURRENT     1		// Current version

/* e_magic index */
#define EI_MAG0      0			// File identification
#define EI_MAG1      1			// File identification
#define EI_MAG2      2			// File identification
#define EI_MAG3      3			// File identification
#define EI_CLASS     4			// File class
#define EI_DATA      5			// Data encoding
#define EI_VERSION   6			// File version
#define EI_PAD       7			// Start of padding bytes

#define ELFMAG0    0x7f			// e_ident[EI_MAG0]
#define ELFMAG1    'E'			// e_ident[EI_MAG1]
#define ELFMAG2    'L'			// e_ident[EI_MAG2]
#define ELFMAG3    'F'			// e_ident[EI_MAG3]

/* e_class */
#define ELFCLASSNONE       0		// Invalid class
#define ELFCLASS32         1		// 32-bit objects
#define ELFCLASS64         2		// 64-bit objects

#define ELFDATANONE        0		// Invalid data encoding
#define ELFDATA2LSB        1		// See below
#define ELFDATA2MSB        2		// See below

typedef struct
{
      Elf32_Word sh_name;
      Elf32_Word sh_type;
      Elf32_Word sh_flags;
      Elf32_Addr sh_addr;
      Elf32_Off  sh_offset;
      Elf32_Word sh_size;
      Elf32_Word sh_link;
      Elf32_Word sh_info;
      Elf32_Word sh_addralign;
      Elf32_Word sh_entsize;
} Elf32_Shdr;

#define SHN_UNDEF 0
#define SHN_LORESERVE 0xff00
#define SHN_LOPROC 0xff00
#define SHN_HIPROC 0xff1f
#define SHN_ABS 0xfff1
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff

#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff


typedef struct
{
	Elf32_Word st_name;
	Elf32_Addr st_value;
	Elf32_Word st_size;
	unsigned char st_info;
	unsigned char st_other;
	Elf32_Half st_shndx;
} Elf32_Sym;

#define ELF32_ST_BIND(i) ((i)>>4)
#define ELF32_ST_TYPE(i) ((i)&0xf)
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))

#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STB_LOPROC 13
#define STB_HIPROC 15


#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define STT_LOPROC 13
#define STT_HIPROC 15 

typedef struct
{
	Elf32_Addr r_offset;
	Elf32_Word r_info;
} Elf32_Rel;

typedef struct
{
	Elf32_Addr r_offset;
	Elf32_Word r_info;
	Elf32_Sword r_addend;
} Elf32_Rela;


#define ELF32_R_SYM(i) ((i)>>8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) (((s)<<8) + (unsigned char)(t))

#define R_386_NONE 0			//none none
#define R_386_32 1			//word32 S + A
#define R_386_PC32 2			//word32 S + A - P
#define R_386_GOT32 3			//word32 G + A - P
#define R_386_PLT32 4			//word32 L + A - P
#define R_386_COPY 5			//none none
#define R_386_GLOB_DAT 6		//word32 S
#define R_386_JMP_SLOT 7		//word32 S
#define R_386_RELATIVE 8		//word32 B + A
#define R_386_GOTOFF 9			//word32 S + A - GOT
#define R_386_GOTPC 10			//word32 GOT + A - P


#define NR_HASH_SIZE	100

#define get_elf_string_section(x, y)	get_elf_section(x, y, SHT_STRTAB)
#define get_elf_symtab_section(x, y)	get_elf_section(x, y, SHT_SYMTAB)
#define get_elf_rel_section(x, y)	get_elf_section(x, y, SHT_REL)

struct _module_struct;

char * get_elf_string(Elf32_Ehdr *pHeader, Elf32_Shdr *pSect, unsigned long index);
Elf32_Ehdr * get_elf_header(void *buffer);
BOOLEAN enum_all_sections(Elf32_Ehdr *pHeader);
BOOLEAN enum_all_symtab(struct _module_struct *m, Elf32_Ehdr *pHeader);
BOOLEAN enum_all_rel(struct _module_struct *m);

#ifdef CNIX
#define printf(fmt, args...)
#endif

#endif
